Skip to content

DuckAi/Voice chat: Allow voice chat to run in background#8317

Merged
karlenDimla merged 3 commits intodevelopfrom
feature/karl/duckai/voicechat-bg
Apr 22, 2026
Merged

DuckAi/Voice chat: Allow voice chat to run in background#8317
karlenDimla merged 3 commits intodevelopfrom
feature/karl/duckai/voicechat-bg

Conversation

@karlenDimla
Copy link
Copy Markdown
Contributor

@karlenDimla karlenDimla commented Apr 17, 2026

Task/Issue URL: https://app.asana.com/1/137249556945/project/1208671677432066/task/1214087464606240?focus=true

Description

Enables Duck.ai voice mode to retain microphone access when the app is backgrounded.

Previously, Android would cut off microphone access as soon as the app left the foreground, interrupting any active voice session. This change introduces a foreground service (DuckChatVoiceMicrophoneService)
that is started when a voice session begins and stopped when it ends, signalling to Android that microphone use is intentional and keeping the process alive in the background.

Changes

  • DuckChatVoiceMicrophoneService — new foreground service that displays a persistent notification while a voice session is active, satisfying Android's background microphone requirements
  • VoiceSessionStateManager — new component that tracks the active voice session and its associated tab. Automatically ends the session (and stops the service) when:
    • The Duck.ai tab is closed
    • The app fully exits (swipe from recents)
    • The app is fresh-launched after a process kill
    • The Duck.ai frontend sends a voiceSessionEnded message
  • BrowserTabViewModel — passes tabId into processJsCallbackMessage so the session manager can correctly identify which tab owns the voice session and avoid ending the session when an unrelated tab is closed
  • AndroidManifest — adds FOREGROUND_SERVICE, FOREGROUND_SERVICE_MICROPHONE, and RECORD_AUDIO permissions, and registers the service with foregroundServiceType="microphone"

NOTE: This does not consider multiple duck.ai voice sessions.

Steps to test this PR

Prerequisites: Enable Search & Duck.Ai

Background app — microphone stays active

  • Open Duck.ai and start a voice session
  • Press the Home button to background the app
  • Expected: A persistent notification appears ("Duck.ai Voice" or similar). Voice continues picking up audio in the background.

Return from background — session intact

  • Complete step 1–2 above
  • Re-open the app from the Recent Apps switcher or tap the notification
  • Expected: The notification disappears. The voice session is still active in Duck.ai.

Swipe app away from recents — session ends

  • Open Duck.ai and start a voice session
  • Open the Recent Apps switcher and swipe the app away
  • Expected: The notification is dismissed. The foreground service stops.

Close the Duck.ai tab — session ends

  • Open Duck.ai and start a voice session
  • Close the Duck.ai tab (via the tab switcher)
  • Expected: The notification disappears immediately. The voice session ends.

Closing a different tab — session unaffected

  • Open Duck.ai and start a voice session, plus at least one other tab
  • Close any tab that is NOT the Duck.ai tab
  • Expected: The notification remains. The voice session continues.

Voice session ended by Duck.ai UI — service stops

  • Open Duck.ai and start a voice session
  • End the voice session within Duck.ai (e.g. tap stop/end)
  • Expected: The notification disappears.

Fresh app launch — no stale session

  • Force-stop the app while a voice session notification is visible
  • Re-launch the app
  • Expected: No notification appears. No stale session is active.

Note

Medium Risk
Introduces a new microphone foreground service and additional permissions, which can impact privacy expectations, battery, and lifecycle correctness if mis-triggered. Risk is moderated by being scoped to voice sessions and gated behind a feature toggle.

Overview
Enables Duck.ai voice chat to continue while the app is backgrounded by introducing DuckChatVoiceMicrophoneService, a microphone foreground service that shows a persistent notification during an active voice session.

Voice session tracking is expanded to be tab-aware (VoiceSessionStateManager.onVoiceSessionStarted(tabId)), optionally starts/stops the foreground service behind a new duckAiVoiceChatService feature toggle, and automatically ends the session when the owning tab is closed or on app fresh launch/exit. BrowserTabViewModel now passes tabId through JS callbacks so the voice session can be associated with the correct tab, and the DuckChat manifest adds the required foreground-service/microphone/audio permissions plus registers the new service.

Reviewed by Cursor Bugbot for commit 8046599. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@karlenDimla karlenDimla force-pushed the feature/karl/duckai/voicechat-bg branch 2 times, most recently from e67cfe3 to 3706f37 Compare April 17, 2026 14:46
@karlenDimla karlenDimla force-pushed the feature/karl/duckai/voicechat-bg branch from 67fc4e6 to d57f881 Compare April 17, 2026 16:22
@karlenDimla karlenDimla requested a review from aitorvs April 20, 2026 05:48
Copy link
Copy Markdown
Collaborator

@aitorvs aitorvs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, works as expected.

We chatted already about it, I'd put it behind a feature flag though.

@karlenDimla karlenDimla force-pushed the feature/karl/duckai/voicechat-bg branch 2 times, most recently from 0dac245 to 68691ce Compare April 22, 2026 06:23
@karlenDimla karlenDimla force-pushed the feature/karl/duckai/voicechat-bg branch from 68691ce to 3a91197 Compare April 22, 2026 06:38
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3a91197. Configure here.

@karlenDimla karlenDimla force-pushed the feature/karl/duckai/voicechat-bg branch from 3a91197 to 8046599 Compare April 22, 2026 06:54
@karlenDimla karlenDimla merged commit f3a270f into develop Apr 22, 2026
11 checks passed
@karlenDimla karlenDimla deleted the feature/karl/duckai/voicechat-bg branch April 22, 2026 07:35
malmstein pushed a commit that referenced this pull request Apr 22, 2026
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1208671677432066/task/1214087464606240?focus=true

### Description
Enables Duck.ai voice mode to retain microphone access when the app is
backgrounded.
   
Previously, Android would cut off microphone access as soon as the app
left the foreground, interrupting any active voice session. This change
introduces a foreground service (DuckChatVoiceMicrophoneService)
that is started when a voice session begins and stopped when it ends,
signalling to Android that microphone use is intentional and keeping the
process alive in the background.
Changes
- DuckChatVoiceMicrophoneService — new foreground service that displays
a persistent notification while a voice session is active, satisfying
Android's background microphone requirements
- VoiceSessionStateManager — new component that tracks the active voice
session and its associated tab. Automatically ends the session (and
stops the service) when:
- The Duck.ai tab is closed
- The app fully exits (swipe from recents)
- The app is fresh-launched after a process kill
- The Duck.ai frontend sends a voiceSessionEnded message
- BrowserTabViewModel — passes tabId into processJsCallbackMessage so
the session manager can correctly identify which tab owns the voice
session and avoid ending the session when an unrelated tab is closed
- AndroidManifest — adds FOREGROUND_SERVICE,
FOREGROUND_SERVICE_MICROPHONE, and RECORD_AUDIO permissions, and
registers the service with foregroundServiceType="microphone"
NOTE: This does not consider multiple duck.ai voice sessions.

### Steps to test this PR

Prerequisites: Enable Search & Duck.Ai

_Background app — microphone stays active_
- [ ] Open Duck.ai and start a voice session
- [ ] Press the Home button to background the app
- [ ] Expected: A persistent notification appears ("Duck.ai Voice" or
similar). Voice continues picking up audio in the background.

_Return from background — session intact_
- [ ] Complete step 1–2 above
- [ ] Re-open the app from the Recent Apps switcher or tap the
notification
- [ ] Expected: The notification disappears. The voice session is still
active in Duck.ai.

_Swipe app away from recents — session ends_

- [ ] Open Duck.ai and start a voice session
- [ ] Open the Recent Apps switcher and swipe the app away
- [ ] Expected: The notification is dismissed. The foreground service
stops.

_Close the Duck.ai tab — session ends_

- [ ] Open Duck.ai and start a voice session
- [ ] Close the Duck.ai tab (via the tab switcher)
- [ ] Expected: The notification disappears immediately. The voice
session ends.

_Closing a different tab — session unaffected_
- [ ] Open Duck.ai and start a voice session, plus at least one other
tab
- [ ] Close any tab that is NOT the Duck.ai tab
- [ ] Expected: The notification remains. The voice session continues.

_Voice session ended by Duck.ai UI — service stops_

- [ ] Open Duck.ai and start a voice session
- [ ] End the voice session within Duck.ai (e.g. tap stop/end)
- [ ] Expected: The notification disappears.

_Fresh app launch — no stale session_

- [ ] Force-stop the app while a voice session notification is visible
- [ ] Re-launch the app
- [ ] Expected: No notification appears. No stale session is active.




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces a new microphone foreground service and additional
permissions, which can impact privacy expectations, battery, and
lifecycle correctness if mis-triggered. Risk is moderated by being
scoped to voice sessions and gated behind a feature toggle.
> 
> **Overview**
> Enables Duck.ai voice chat to continue while the app is backgrounded
by introducing `DuckChatVoiceMicrophoneService`, a microphone foreground
service that shows a persistent notification during an active voice
session.
> 
> Voice session tracking is expanded to be *tab-aware*
(`VoiceSessionStateManager.onVoiceSessionStarted(tabId)`), optionally
starts/stops the foreground service behind a new
`duckAiVoiceChatService` feature toggle, and automatically ends the
session when the owning tab is closed or on app fresh launch/exit.
`BrowserTabViewModel` now passes `tabId` through JS callbacks so the
voice session can be associated with the correct tab, and the DuckChat
manifest adds the required foreground-service/microphone/audio
permissions plus registers the new service.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8046599. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants